From e1a85a607c5599d4116ecd6394a33674875581b9 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 26 Apr 2017 01:16:17 +0100 Subject: [PATCH] Add support for custom target-specific runners When `target.$triple.runner` is specified, it will be used for any execution commands by cargo including `cargo run`, `cargo test` and `cargo bench`. The original file is passed to the runner executable as a first argument. This allows to run tests when cross-comping Rust projects. This is not a complete solution, and might be extended in future for better ergonomics to support passing extra arguments to the runner itself or overriding runner from command line, but it should already unlock major existing usecases. Fixes #1411 Resolves #3626 --- src/cargo/ops/cargo_compile.rs | 7 ++-- src/cargo/ops/cargo_rustc/compilation.rs | 21 +++++++++-- tests/tool-paths.rs | 45 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 1256787f4..26faf702e 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -662,8 +662,11 @@ fn scrape_target_config(config: &Config, triple: &str) None => return Ok(ret), }; for (lib_name, value) in table { - if lib_name == "ar" || lib_name == "linker" || lib_name == "rustflags" { - continue + match lib_name.as_str() { + "ar" | "linker" | "runner" | "rustflags" => { + continue + }, + _ => {} } let mut output = BuildOutput { diff --git a/src/cargo/ops/cargo_rustc/compilation.rs b/src/cargo/ops/cargo_rustc/compilation.rs index b34850a79..594f3cb19 100644 --- a/src/cargo/ops/cargo_rustc/compilation.rs +++ b/src/cargo/ops/cargo_rustc/compilation.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use semver::Version; use core::{PackageId, Package, Target, TargetKind}; -use util::{self, CargoResult, Config, ProcessBuilder, process, join_paths}; +use util::{self, CargoResult, Config, LazyCell, ProcessBuilder, process, join_paths}; /// A structure returning the result of a compilation. pub struct Compilation<'cfg> { @@ -53,6 +53,8 @@ pub struct Compilation<'cfg> { pub target: String, config: &'cfg Config, + + target_runner: LazyCell>, } impl<'cfg> Compilation<'cfg> { @@ -72,6 +74,7 @@ impl<'cfg> Compilation<'cfg> { cfgs: HashMap::new(), config: config, target: String::new(), + target_runner: LazyCell::new(), } } @@ -91,10 +94,24 @@ impl<'cfg> Compilation<'cfg> { self.fill_env(process(cmd), pkg, true) } + fn target_runner(&self) -> CargoResult<&Option> { + self.target_runner.get_or_try_init(|| { + let key = format!("target.{}.runner", self.target); + Ok(self.config.get_path(&key)?.map(|v| v.val)) + }) + } + /// See `process`. pub fn target_process>(&self, cmd: T, pkg: &Package) -> CargoResult { - self.fill_env(process(cmd), pkg, false) + let builder = if let &Some(ref runner) = self.target_runner()? { + let mut builder = process(runner); + builder.arg(cmd); + builder + } else { + process(cmd) + }; + self.fill_env(builder, pkg, false) } /// Prepares a new process with an appropriate environment to run against diff --git a/tests/tool-paths.rs b/tests/tool-paths.rs index dcb9e6368..641ccba9a 100644 --- a/tests/tool-paths.rs +++ b/tests/tool-paths.rs @@ -124,3 +124,48 @@ fn relative_tools() { [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", url = foo_url, ar = output.0, linker = output.1))) } + +#[test] +fn custom_runner() { + let target = rustc_host(); + + let foo = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.1" + "#) + .file("src/main.rs", "fn main() {}") + .file("tests/test.rs", "") + .file("benches/bench.rs", "") + .file(".cargo/config", &format!(r#" + [target.{}] + runner = "nonexistent-runner" + "#, target)); + + foo.build(); + + assert_that(foo.cargo("run").args(&["--", "--param"]), + execs().with_stderr_contains(&format!("\ +[COMPILING] foo v0.0.1 ({url}) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] `nonexistent-runner target[/]debug[/]foo[EXE] --param` +", url = foo.url()))); + + assert_that(foo.cargo("test").args(&["--test", "test", "--verbose", "--", "--param"]), + execs().with_stderr_contains(&format!("\ +[COMPILING] foo v0.0.1 ({url}) +[RUNNING] `rustc [..]` +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] `nonexistent-runner [..][/]target[/]debug[/]deps[/]test-[..][EXE] --param` +", url = foo.url()))); + + assert_that(foo.cargo("bench").args(&["--bench", "bench", "--verbose", "--", "--param"]), + execs().with_stderr_contains(&format!("\ +[COMPILING] foo v0.0.1 ({url}) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] release [optimized] target(s) in [..] +[RUNNING] `nonexistent-runner [..][/]target[/]release[/]deps[/]bench-[..][EXE] --param --bench` +", url = foo.url()))); +} -- 2.30.2